#!/bin/bash
# 防火墙管理脚本
# 作者: 丁文
# 时间: 2025-04-09 22:00:05

DEFAULT_ZONE="public"

# Colored output
info()    { echo -e "\033[1;34m[INFO] $*\033[0m"; }
success() { echo -e "\033[1;32m[SUCCESS] $*\033[0m"; }
error()   { echo -e "\033[1;31m[ERROR] $*\033[0m"; }

# Ensure the script runs as root
if [ "$EUID" -ne 0 ]; then
    error "Please run this script as root."
    exit 1
fi

# Check firewalld availability
if ! command -v firewall-cmd >/dev/null; then
    error "firewalld is not installed. Run: yum install -y firewalld"
    exit 1
fi

# Start firewalld if not running
if ! systemctl is-active --quiet firewalld; then
    info "firewalld is not active. Starting it now..."
    systemctl start firewalld
    systemctl enable firewalld
    sleep 1
fi

# Help message
show_help() {
    echo "Usage: $0 <command> [args]"
    echo ""
    echo "Commands:"
    echo "  status                         Show firewalld status"
    echo "  start|stop|restart             Manage firewalld service"
    echo "  list [zone]                    List open ports (default zone: $DEFAULT_ZONE)"
    echo "  open <port[,port]> [tcp|udp]  Open port(s), default protocol is tcp"
    echo "  close <port[,port]> [tcp|udp] Close port(s), default protocol is tcp"
    echo "  reload                         Reload firewalld configuration"
    echo "  help                           Show this help message"
    echo ""
    echo "Examples:"
    echo "  $0 open 80,443"
    echo "  $0 close 3306 udp"
    echo "  $0 list internal"
}

# Command dispatch
case "$1" in
    status)
        systemctl status firewalld
        ;;
    start|stop|restart)
        systemctl $1 firewalld && success "firewalld $1ed"
        ;;
    list)
        ZONE=${2:-$DEFAULT_ZONE}
        info "Open ports in zone [$ZONE]:"
        firewall-cmd --zone="$ZONE" --list-ports
        ;;
    open)
        PORTS=$2
        PROTOCOL=${3:-tcp}
        ZONE=${4:-$DEFAULT_ZONE}
        if [ -z "$PORTS" ]; then
            error "Please specify one or more ports to open."
            exit 1
        fi
        IFS=',' read -ra PORT_ARR <<< "$PORTS"
        for PORT in "${PORT_ARR[@]}"; do
            firewall-cmd --zone="$ZONE" --add-port="${PORT}/${PROTOCOL}" --permanent && \
                success "Port opened: $PORT/$PROTOCOL"
        done
        firewall-cmd --reload
        ;;
    close)
        PORTS=$2
        PROTOCOL=${3:-tcp}
        ZONE=${4:-$DEFAULT_ZONE}
        if [ -z "$PORTS" ]; then
            error "Please specify one or more ports to close."
            exit 1
        fi
        IFS=',' read -ra PORT_ARR <<< "$PORTS"
        for PORT in "${PORT_ARR[@]}"; do
            firewall-cmd --zone="$ZONE" --remove-port="${PORT}/${PROTOCOL}" --permanent && \
                success "Port closed: $PORT/$PROTOCOL"
        done
        firewall-cmd --reload
        ;;
    reload)
        firewall-cmd --reload && success "firewalld configuration reloaded"
        ;;
    help|--help|-h)
        show_help
        ;;
    *)
        error "Unknown command: $1"
        show_help
        ;;
esac

